using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace ChildrenOfWar
{
    class COW_Person
    {
        List<Vector2> PathNodeQueue;    // First in, last out queue of pathnodes to which to go.

        Vector2 position;               // Position of Person in XY plane
        Random rand = new Random();

        double velocity;               // Per-update movement speed of the Person

        Vector2 DEFAULTSTARTPOS = new Vector2(0, 0);

        const double DEFAULTVELOCITY = 3;

        /// <summary>
        /// Creates new instance of COW_Person with movement speed 3 at 0,0.
        /// </summary>
        public COW_Person()
        {
            velocity = DEFAULTVELOCITY;
            position = DEFAULTSTARTPOS;
            PathNodeQueue = new List<Vector2>();
        }

        /// <summary>
        /// Creates new instance of COW_Person.
        /// </summary>
        /// <param name="Vel">Maximum movement speed for Person</param>
        /// <param name="StartPos">Initial position of Person</param>
        public COW_Person(double Vel, Vector2 StartPos)
        {
            velocity = Vel;
            position = StartPos;
            PathNodeQueue = new List<Vector2>();
        }

        /// <summary>
        /// Adds the most efficient legal path to the LILO queue of movements.
        /// </summary>
        /// <param name="nextPathNode">End point of the next movement.</param>
        public void addPathNode(Vector2 nextPathNode)
        {
            checkPathClear(nextPathNode, PathNodeQueue[PathNodeQueue.Count - 1]);
            PathNodeQueue.Add(nextPathNode);
        }

        //METHOD INCOMPLETE
        /// <summary>
        /// NYI: Checks whether a direct line between two points is legal.
        /// If illegal, calls methods to split path into legal segments.
        /// </summary>
        /// <param name="beginningPoint">Initial point on path.</param>
        /// <param name="endPoint">Final point on path.</param>
        public void checkPathClear( Vector2 beginningPoint, Vector2 endPoint)     // Method which will check if the path is clear from the beginning point, along PathToCheck
        {
            COW_Obstacle ObstInWay = ObstacleOnLine(beginningPoint, endPoint);
            if (ObstInWay != null)  // TBI: Detects if any are in the way, outputs first obstacle encountered to ObstInWay (a parameter)
            {
                Vector2 intermediateNode = findOptimalNode(endPoint, beginningPoint, ObstInWay);
                addPathNode(intermediateNode); // should create recursive/co-routine loop: it will now add this node, then look for any blocks in the new path
            }
        }

        //METHOD INCOMPLETE
        /// <summary>
        /// NYI! Finds the most efficient path to take to circumvent an Obstacle.
        /// </summary>
        /// <param name="beginningPoint">Initial point on path.</param>
        /// <param name="endPoint">Endpoint of path.</param>
        /// <param name="Obst">Obstacle around which to navigate.</param>
        /// <returns>Returns the intermediate node created.</returns>
        public Vector2 findOptimalNode(Vector2 beginningPoint, Vector2 endPoint, COW_Obstacle Obst)
        {
            return new Vector2(rand.Next(800), rand.Next(600)); // TBI: Determine the optimal point  
        }

        //METHOD INCOMPLETE
        /// <summary>
        /// Checks if any Obstacles are on the line between two points.
        /// </summary>
        /// <param name="beginningPoint">Initial point on path.</param>
        /// <param name="endPoint">Final point on path.</param
        /// <returns>Returns the first Obstacle encountered.</returns>
        public COW_Obstacle ObstacleOnLine(Vector2 beginningPoint, Vector2 endPoint)
        {
            COW_Obstacle Obst = new COW_Obstacle();
            if (rand.NextDouble() > 0.5) // TBI: sees if the obstacle is here
                return Obst;
            else return null;
        }

        /// <summary>
        /// Removes all path nodes for the Person.
        /// </summary>
        public void clearPath()
        {
            PathNodeQueue.Clear();
        }

        /// <summary>
        /// Checks whether the Person has reached the first node in the PathNodeQueue.
        /// If they have reached, removes the current target node, setting a new target.
        /// After this check, moves to the target node.
        /// </summary>
        public virtual void Move()
        {
            if (PathNodeQueue.Count > 0)
            {
                while (Vector2.Distance(PathNodeQueue[0], position) < velocity)
                {
                    PathNodeQueue.Remove(PathNodeQueue[0]);
                }
                Vector2 moveVector = PathNodeQueue[0] - position;
                moveVector.Normalize();
                moveVector.X *= (float)velocity;
                moveVector.Y *= (float)velocity;
                position += moveVector;
            }
        }
    }
}